/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFVPID
  \brief the base class for the PID classes
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2023-06-02
  \date 2023-06-05 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2023-06-02   <td>Asia Sun    <td>file created                  </tr>
  <tr>  <td>2023-06-05   <td>Asia Sun    <td>separated from ETFPID         </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFVPID_h
#define ETFVPID_h

#include <Rtypes.h>
#include <TTree.h>

class TGraph;
class TLegend;

class ETFRun;
class ETFVMEEvent;
class ETFVMERawEvent;
class ETFPXISection;
class ETFDetectorManager;
class ETFTrackManager;
class ETFParaManager;

class ETFVPID{
public:
  ETFVPID();
  virtual ~ETFVPID();

  virtual void Configure(); ///< assign all the managers
  virtual void Initialize();
  virtual void Reset(){ Initialize(); }
  virtual void Register() = 0; ///< register to the main tree
  
  /// propogate the particle in the dipole magnet to meet the tracks given by the DCs
  /// currently and usually a uniform magnetic field is assumed, as it is both
  /// appropriate and efficient
  /// \param pIn[0-1]: {k, b} from postTaTrk
  /// \param pOut[0-1]: {k, b} from postMagTrk
  /// \param tof2: from tstop to TOFWall
  /// to be implemented in derived classes
  virtual bool Fly(const double *pIn, const double *pOut, double tof2){ return true; }
  
  /// propogate the particle in the dipole magnet from the target-hit point
  /// to meet the post-mag trk
  /// \param pOut[0-1]: {k, b} from postMagTrk
  /// \param tof2: from tstop to TOFWall
  /// to be implemented in derived classes
  virtual bool Fly(const double *pOut, double tof2){ return true; }
  
  /// \brief the general fly function that will actually be called by the program
  /// \param istof: whether we only call fly to calculate tof
  /// to be implemented in derived classes
  virtual bool Fly(bool istof = false){ return true; }
  
  bool HasFlied() const{ return fHasFlied; }
  bool FlySuccess(){ return fFlySuccess; }
  void SetMagneticIntensity(double b){ SetB(b); } ///< in Tesla
  void SetB(double b){ kB = b; }
  virtual void ConstructGraph(); ///< update fCurve
  virtual void Draw();
  /// \return the currentevent index
  int Index() const; /// { return fdm->Index(); }
  double tof2_ofst() const{ return ftof2_ofst; }

  virtual void Print();

  static const double L; //! ///< = 25881.; // distance from Tstart to Tstop in mm
  /// some physical constants
  static const double c0; //! ///< = ETFMath::c0(); // in mm/ns
  static const double u0; //! ///< = ETFMath::uMeV(); // in MeV
  /// CC = 0.321840605 = e0/(u0*c0*1E6) SI unit
  static const double CC; //! ///< = 0.32184060506023993;
  static const double HPI, PI; //! /// pi/2, pi
  // the z border of the effective magField (in mm)
  static const double kzMagIn, kzMagOut; //! /// ETFMath::zMagIn(), ETFMath::zMagOut()
  static double kB; //! ///< the effective magnetic intensity of the dipole magnet, in Tesla

  ClassDef(ETFVPID, 1); ///< particle identification

protected:
  bool fHasFlied; //! ///< whether PID has been done
  bool fFlySuccess; //! ///< whether PID has been successful

  // z position of the target and the tstop detector
  double fTstopZ; //! ///< tstop Z position
  double fTaZ; //! ///< target Z position

  double ftof2_ofst; //! ///< calibration constants for tof2: tof2 += tof2_ofst

  ///@{ for visualization purposes
  TGraph *fGCurve; //! ///< the curve in the dipole magnet
  TLegend *fGLegend; //! ///< mark the aoz of the event
  /// @) for visualization purposes

  // the managers //
  ETFDetectorManager *fdm; //!
  ETFTrackManager *ftm; //!
  ETFParaManager *fpm; //!
  ETFRun *fRun; //!
  TTree *fTree;
};

#endif
